package com.t.bricks.bussiness.component.guest;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.t.bricks.model.Log;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.function.file.FileUtil;
import com.t.bricks.utils.function.json.JacksonShell;
import com.t.bricks.utils.spring.CloudBridgeUtil;
import com.t.bricks.utils.spring.ModuleUtil;

/**
 * 用切面方式监听用户登录的数据操作
 */
@Aspect
@Component
public class GuestLoginLogServiceAspect {
	
	/**
	 * '来宾账户登录信息'存储
	 */
	private static Map<String, List<String>> serviceMap = null;
	
	/**
	 * 注册'来宾账户登录信息'
	 * @param sOwner 账户归属
	 * @param serverName 回调目标服务
	 * @param sInsideKey 请求密钥
	 * @param url 回调目标地址
	 * @return
	 */
	public static synchronized MsgEmity registerService(String sOwner,
			String serverName, String sInsideKey, String url) {
		if (null == sOwner || "".equals(sOwner.trim())) {
			return MsgEmity.err(9101, "归属参数为空");
		}
		
		if (null == serverName || "".equals(serverName.trim())) {
			return MsgEmity.err(9102, "回调目标服务参数为空");
		}
		
		if (null == url || "".equals(url.trim())) {
			return MsgEmity.err(9103, "回调目标地址参数为空");
		}
		
		if (null == serviceMap) {
			serviceMap = new ConcurrentHashMap<String, List<String>>(3);//ConcurrentHashMap是线程安全的,来宾用户类型一般3个够了
		}
		
		serviceMap.put(sOwner.trim(), Arrays.asList(serverName.trim(), sInsideKey.trim(), url));
	
		String filePath = String.format("%s/temp/cache/Guest/LoginCache.txt", System.getProperty("user.dir").replaceAll("\\\\", "/"));
		String json = JacksonShell.toJSONString(serviceMap);
		FileUtil.saveStr(filePath, json);
		
		return MsgEmity.success(9103, "已经注册");
	}
	
	/**
	 * 读取缓存文件
	 */
	@PostConstruct
	private void readCache() {
		String filePath = String.format("%s/temp/cache/Guest/LoginCache.txt", System.getProperty("user.dir").replaceAll("\\\\", "/"));
		MsgEmity me = FileUtil.readFromFile(filePath);
		if (!me.isSuccess()) {
			return;
		}
		
		String json = me.getData();
		if (null == json || "".equals(json.trim())) {
			return;
		}
		
		Map<String, List<String>> map = JacksonShell.toJavaObject(json, Map.class);
		if (null == map || map.size() < 0) {
			return;
		}
		
		if (null == serviceMap) {
			serviceMap = new ConcurrentHashMap<String, List<String>>(map.size());//ConcurrentHashMap是线程安全的
		}
		
		serviceMap.putAll(map);
	}
	
	/**
	 * 定义切入点，切入点为'MsgEmity com.t.bricks.bussiness.server.login.impl.LoginServerImpl'下的in函数,并且函数只有3个参数(用?会异常)
	 * 1、execution(public * *(..)) 任意的公共方法
	 * 2、execution(* set*(..)) 以set开头的所有的方法
	 * 3、execution(* com.lingyejun.annotation.LoggerApply.*(..))com.lingyejun.annotation.LoggerApply这个类里的所有的方法
	 * 4、execution(* com.lingyejun.annotation.*.*(..))com.lingyejun.annotation包下的所有的类的所有的方法
	 * 5、execution(* com.lingyejun.annotation..*.*(..))com.lingyejun.annotation包及子包下所有的类的所有的方法
	 * 6、execution(* com.lingyejun.annotation..*.*(String,?,Long)) com.lingyejun.annotation包及子包下所有的类的有三个参数，第一个参数为String类型，第二个参数为任意类型，第三个参数为Long类型的方法
	 * 7、execution(@annotation(com.lingyejun.annotation.Lingyejun))
	 */
	@Pointcut(value = "execution(com.t.bricks.model.MsgEmity com.t.bricks.bussiness.server.login.impl.LoginServer*.in(String,String,String,Integer))")
	public void inMethod() {
	}

	/**
	 * 后置/返回值增强
     * @param joinPoint
     * @param result 被切点方法执行后的返回值
     * @return
	 */
	@AfterReturning(returning="result", pointcut="inMethod()")
	public void afterReturningByIn(JoinPoint joinPoint, Object result) {
		if (!(result instanceof MsgEmity)) {//不是返回MsgEmity,则说明不是要进行的
			MethodSignature signature = (MethodSignature) joinPoint.getSignature();
			String methodName = signature.getMethod().getName();
			Log.error("方法'", methodName, "'返回数据不是MsgEmity");
			return;
		}

		MsgEmity me = (MsgEmity)result;
		if (!me.isSuccess()) {
			return;			//原方法执行失败,不处理
		}
		
		add(joinPoint, me);	//多线程处理
	}

	/**
	 * 添加数据
	 * @param joinPoint
	 * @param msgEmity
	 */
	private void add(JoinPoint joinPoint, MsgEmity msgEmity) {
		Object[] methodArgs = joinPoint.getArgs();
		if (null == methodArgs || methodArgs.length < 4) {
			return;
		}
		
		String sOwner = String.valueOf(methodArgs[2]);
		if (null == sOwner || sOwner.contains("BricksBaseSystem.")) {
			return;//基本系统服务库下的操作
		}
		
		if (null == serviceMap || serviceMap.size() < 1 || !serviceMap.containsKey(sOwner)) {
			Log.error("发现未进行注册的业务账户类型登录:", sOwner);
			return;//没有注册
		}
		
		List<String> callbackInfo = serviceMap.get(sOwner);
		
		Map<String, Object> parameters = new HashMap<String, Object>(4);
		parameters.put("sNameOrNo", String.valueOf(methodArgs[0]));//第一个参数为用户登录名(或工号)
		parameters.put("sIp", ModuleUtil.currentLoginUserIp());
		parameters.put("sDevice", String.valueOf(methodArgs[3]));
		parameters.put("sMACAddress", null);
		
		Map<String, String> hearMap = new HashMap<String, String>(1);
		hearMap.put("sInsideKey", callbackInfo.get(1));
		
		CloudBridgeUtil.post(
				callbackInfo.get(0),
				callbackInfo.get(2),
				parameters,
				MsgEmity.class,//bridgeDao.post访问的方法中返回的数据类型
				false,
				hearMap);
	}
		
}
